#include "debug.h"
#include "pwm.h"
#include "uart.h"
#include "modbus.h"
#include "flash.h"
#include "mytime.h"

extern uint16_t Reg[Reg_num];  // 寄存器数组
extern MODBUS modbus;          // Modbus协议结构体

typedef struct
{
    uint16_t slave_station;  // 读写设备从站站号
    uint16_t baud_rate;      // 读写设备波特率
    float servo_angle[8];    // 舵机角度组
} SERVO;

SERVO servo;
uint16_t BTL_XZ = 4;
uint16_t BTL[] = {4800, 9600, 19200, 38400, 57600};

union {
    float f;
    uint16_t u[2];
} value;

void RS485_03 (void);  // 上位机读取数据
void RS485_06 (void);  // 上位机写入数据

int main (void) {
    SystemCoreClockUpdate();
    time_init();

    FLASH_Unlock();
    FLASH_UserOptionByteConfig(OB_IWDG_SW,OB_STOP_NoRST,OB_RST_EN_DT12ms,OB_PowerON_Start_Mode_BOOT);
    FLASH_Lock();

    uint16_t flash_data[256] = {1, 4};  // 默认值：从站地址1，波特率索引4
    flash_load_parameters (flash_data);
    if (flash_data[0] < 1 || flash_data[0] > 247) {
        flash_data[0] = 1;  // 确保从站地址在合法范围内
    }
    if (flash_data[1] < 1 || flash_data[1] > 4) {
        flash_data[1] = 4;  // 默认波特率索引为4
    }

    modbus.myadd = (uint8_t)flash_data[0];
    BTL_XZ = flash_data[1];
    servo.slave_station = modbus.myadd;
    servo.baud_rate = BTL_XZ;
    UARTx_DMA_init (BTL[BTL_XZ]);  // 初始化UART1

// 串口接收相关变量
#define UART_RX_BUF_SIZE 255
    char uart_rx_buf[UART_RX_BUF_SIZE];
    u16 uart_rx_len = 0;
    uint32_t uart_rx_last_time = 0;
    const uint32_t UART_RX_TIMEOUT = 200000;  // 20ms超时（单位: us）

    GPIO_PWM_Init();
    TIM1_PWM_Init();
    TIM2_PWM_Init();

    for (int j = 1; j <= 8; j++) {
        Servo_SetAngle (j, 0);  // 初始化所有舵机到90度
    }

    Modbus_Init();  // 初始化Modbus协议

    while (1) {
        u16 buffer_num = uartAvailable();  // 获取接收缓冲区中可读数据的数量
        if (buffer_num > 0) {
            // 读取新数据到缓存
            if (uart_rx_len + buffer_num > UART_RX_BUF_SIZE)
                buffer_num = UART_RX_BUF_SIZE - uart_rx_len;  // 防止溢出

            uartRead (&uart_rx_buf[uart_rx_len], buffer_num);
            uart_rx_len += buffer_num;
            uart_rx_last_time = time_get();  // 记录最后接收时间
            // printf("%d\r\n",uart_rx_len);
        }

        // 判断是否超时（即一帧数据接收完成）
        if (uart_rx_len > 0 && (time_get() - uart_rx_last_time > UART_RX_TIMEOUT)) {
            RS485_03();       // 上位机读取数据前更新寄存器映射
            if (Modbus_Event ((uint8_t *)uart_rx_buf, uart_rx_len) == 2) {
                RS485_06();   // 处理写入的数据（功能码6或10）
            }
            uart_rx_len = 0;  // 清空缓存，准备接收下一帧
        }
    }
}

/******************************************************
函数名称：void RS485_03()
功能描述: RS485 下位机数据上传上位机
全局变量：
参数说明：
返回说明：
说 明：无
*******************************************************/
void RS485_03 (void) {
    servo.slave_station = modbus.myadd;
    servo.baud_rate = BTL_XZ;

    Reg[0] = servo.slave_station;
    Reg[1] = servo.baud_rate;

    for (int i = 0; i < 8; i++) {
        value.f = servo.servo_angle[i];
        Reg[(i + 1) * 2] = value.u[1];
        Reg[(i + 1) * 2 + 1] = value.u[0];
    }
}

/******************************************************
函数名称：void RS485_06()
功能描述: RS485 上位机数据写入下位机寄存器
全局变量：
参数说明：
返回说明：
说 明：无
*******************************************************/
void RS485_06 (void) {
    servo.slave_station = Reg[0];
    servo.baud_rate = Reg[1];

    float angle_last[8];
    uint8_t angle_fla[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    uint8_t yes = 0;

    for (int i = 0; i < 8; i++) {
        angle_last[i] = servo.servo_angle[i];
    }

    for (int i = 0; i < 8; i++) {
        value.u[1] = Reg[(i + 1) * 2];
        value.u[0] = Reg[(i + 1) * 2 + 1];
        servo.servo_angle[i] = value.f;
        // printf("Servo %d angle: %.2f\n ,Reg[%d]: %d, Reg[%d]: %d\n", i + 1, servo.servo_angle[i], (i + 1) * 2, Reg[(i + 1) * 2], (i + 1) * 2 + 1, Reg[(i + 1) * 2 + 1]);
    }

    if (BTL_XZ != servo.baud_rate) {
        UARTx_DMA_init (BTL[servo.baud_rate]);  // 更新波特率
    }

    modbus.myadd = servo.slave_station;
    BTL_XZ = servo.baud_rate;

    int i = 0;
    while (yes != 8) {
        if (servo.servo_angle[i] > angle_last[i]) {
            angle_last[i] = angle_last[i] + 1;
            Servo_SetAngle (i + 1, angle_last[i]);
        } else if (servo.servo_angle[i] < angle_last[i]) {
            angle_last[i] = angle_last[i] - 1;
            Servo_SetAngle (i + 1, angle_last[i]);
        } else if (servo.servo_angle[i] == angle_last[i]) {
            angle_fla[i] = 1;
        }
        i++;

        if (i >= 8) {
            yes = 0;
            for (int j = 0; j < 8; j++) {
                yes = angle_fla[j] + yes;
            }
            i = 0;
            Delay_Ms (15);
        }
    }

    // 保存到flash
    uint16_t flash_data[256];
    flash_data[0] = (uint16_t)modbus.myadd;
    flash_data[1] = (uint16_t)BTL_XZ;
    flash_save_parameters (flash_data);
}